package com.meritdata.cloud.data.manager.access.service.impl;

import com.meritdata.cloud.data.base.ResultData;
import com.meritdata.cloud.data.manager.access.entity.QTdDataSource;
import com.meritdata.cloud.data.manager.access.entity.TdDataSource;
import com.meritdata.cloud.data.manager.access.repository.DataSourceRepository;
import com.meritdata.cloud.data.manager.access.service.IDataSourceService;
import com.meritdata.cloud.data.util.Base64Util;
import com.mysql.jdbc.Connection;
import com.querydsl.core.types.ExpressionUtils;
import com.querydsl.core.types.Predicate;
import com.querydsl.jpa.impl.JPAQuery;
import com.querydsl.jpa.impl.JPAQueryFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.io.UnsupportedEncodingException;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;

@Service
public class DataSourceService implements IDataSourceService {
    @Autowired
    private DataSourceRepository dataSourceRepository;

    @Autowired
    private JPAQueryFactory jpaQueryFactory;

    @Override
    public List<TdDataSource> list() {
        return dataSourceRepository.findAll();
    }

    @Override
    public TdDataSource getById(Long id) {
        QTdDataSource qTdDataSource = QTdDataSource.tdDataSource;
        Predicate predicate = (Predicate) qTdDataSource.isNotNull().or(qTdDataSource.isNull());
        predicate = id == null ? ExpressionUtils.and(predicate, qTdDataSource.id.isNull()) : ExpressionUtils.and(predicate, qTdDataSource.id.eq(id));
        TdDataSource ds = jpaQueryFactory.selectFrom(qTdDataSource).where(predicate).fetchFirst();
        try {
            String password = Base64Util.decode(ds.getPassword());
            ds.setPassword(password);
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
        return ds;
    }

    @Override
    @Transactional
    public Boolean changeDbStatusById(int enable, Long id) {
        QTdDataSource qTdDataSource = QTdDataSource.tdDataSource;
        Predicate predicate = (Predicate) qTdDataSource.isNotNull().or(qTdDataSource.isNull());
        predicate = id == null ? ExpressionUtils.and(predicate, qTdDataSource.id.isNull()) : ExpressionUtils.and(predicate, qTdDataSource.id.eq(id));
        jpaQueryFactory.update(qTdDataSource).where(predicate).set(qTdDataSource.enable, enable).execute();
        return true;
    }

    @Override
    @Transactional
    public Boolean delete(Long id) {
        ResultData result = new ResultData();
        try {
            TdDataSource ds = getById(id);
            dataSourceRepository.delete(ds);
        } catch (Exception e) {
            return false;
        }
        return true;
    }

    @Override
    public TdDataSource create(String name, String description, String url, String user, String password,
                               int enable, int maxActive, int initialSize, int maxWait,
                               String info, int enableCollection, String type) {
        TdDataSource ds = new TdDataSource();
        ds.setName(name);
        ds.setDescription(description);
        ds.setUrl(url);
        ds.setUser(user);
        try {
            password = Base64Util.encode(password);
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
        ds.setPassword(password);
        ds.setEnable(enable);
        ds.setMaxActive(maxActive);
        ds.setInitialSize(initialSize);
        ds.setMaxWait(maxWait);
        ds.setInfo(info);
        ds.setEnableCollection(enableCollection);
        ds.setType(type);
        ds = dataSourceRepository.save(ds);
        return ds;
    }

    @Override
    public TdDataSource update(Long id, String name, String description, String url, String user, String password, int enable, int maxActive, int initialSize, int maxWait, String info, int enableCollection, String type) {
        TdDataSource ds = getById(id);
        ds.setName(name);
        ds.setDescription(description);
        ds.setUrl(url);
        ds.setUser(user);
        try {
            password = Base64Util.encode(password);
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
        ds.setPassword(password);
        ds.setEnable(enable);
        ds.setMaxActive(maxActive);
        ds.setInitialSize(initialSize);
        ds.setMaxWait(maxWait);
        ds.setInfo(info);
        ds.setEnableCollection(enableCollection);
        ds.setType(type);
        ds = dataSourceRepository.save(ds);
        return ds;
    }

    @Override
    public Boolean connectionTest(String url, String user, String password, String info, String type) {
        Boolean rs = true;
        switch (type) {
            case "mysql":
                rs = sqlConnectionTest(url, user, password, "com.mysql.jdbc.Driver");
                break;
        }
        return rs;
    }

    private boolean sqlConnectionTest(String url, String user, String password
            , String driver) {
        Boolean rs = true;
        try {
            Class.forName(driver);
            Connection con = null;
            try {
                con = (Connection) DriverManager.getConnection(url, user, password);
            } catch (SQLException e) {
                e.printStackTrace();
                return false;
            } finally {
                try {
                    con.close();
                } catch (SQLException e2) {
                    e2.printStackTrace();
                }
            }
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
        return rs;
    }

    @Override
    public Boolean nameExist(Long id,String name) {
        QTdDataSource qTdDataSource = QTdDataSource.tdDataSource;
        Predicate predicate = (Predicate) qTdDataSource.isNotNull().or(qTdDataSource.isNull());
        predicate = name == null ? ExpressionUtils.and(predicate, qTdDataSource.name.isNull()) : ExpressionUtils.and(predicate, qTdDataSource.name.eq(name));
        if(id!=null){
            predicate = ExpressionUtils.and(predicate, qTdDataSource.id.ne(id));
        }
        long ds = jpaQueryFactory.selectFrom(qTdDataSource).where(predicate).fetchCount();
        return ds > 0;
    }

}
